import java.util.ArrayList;

/**
 * Class implementing a predicate
 */

public abstract class Predicate {
    protected ArrayList<Predicate> lstObjects;
    protected int duration;
 
    //Attempts to add an object to the list
    //Returns whether or not it was successful
    @SuppressWarnings("unchecked") public boolean AddToList(Predicate object)
    {
        if(lstObjects.isEmpty())
            return lstObjects.add(object);
        return false;
    }
    //abstract boolean AddToList(Predicate object);
    
    //Returns whether the object exists in the Predicate or not
    public boolean IsInList(Predicate object){
        return lstObjects.contains(object);
    }
    //Returns if the two ArrayLists contains exactly the same elements
    @SuppressWarnings("unchecked") public boolean SameList(ArrayList objects){
    	if(objects==null && lstObjects!=null)
    		return false;
    	if(objects==null && lstObjects==null)
    		return true;
    	if(objects!=null && lstObjects==null)
    		return false;
    	
        return ((objects.containsAll(lstObjects) && lstObjects.containsAll(objects)));
    }
    
    public boolean equals(Predicate o) {
    	
		return this.getClass() == o.getClass();
	}
    
    public boolean equals2(Predicate p){
    	
    	boolean sameList = false;
    	
    	if(this.getClass() == p.getClass() ){
    		sameList = p.SameList(this.lstObjects);
    		if(this instanceof Ingredient){
    			//if the predicat is an ingredient  
    			sameList = (sameList && ( (Ingredient) this).getName().compareTo(((Ingredient) p).getName())== 0);  
    		}
    	}
    
    	return sameList;
    }
  
    
    public String toString() {
    	return lstObjects.toString() + "(" + duration + ")";
    }
    
    public ArrayList<Predicate> getObjects() {
    	return lstObjects;
    }
    
    public int getDuration() {
    	return duration;
    }
    
    public void SetDuration(int duration) {
    	this.duration = duration;
    }
    
    /* public abstract Predicate concretePredicate(Predicate o); */
}

class Chopped extends Predicate
{       
    public Chopped(){
        lstObjects = new ArrayList<Predicate>(1);
        duration = 2;
    }
    
    @SuppressWarnings("unchecked") public Chopped(Predicate object){
        this();
        lstObjects.add(object);
    }
    

    public String toString() {
    	return "Chopped " + super.toString();
    }
}

class Mixed extends Predicate
{       
    public Mixed(){
        lstObjects = new ArrayList<Predicate>();
        duration = 3;
    }
   
    public Mixed(ArrayList<Predicate> objects){
        lstObjects = objects;
    }
    
    @SuppressWarnings("unchecked") @Override public boolean AddToList(Predicate object)
    {
            return lstObjects.add(object);
    }
    
 
    
    public String toString() {
    	return "Mixed " + super.toString();
    }

}

class Fried extends Predicate
{       
    Fried(){
        lstObjects = new ArrayList<Predicate>(1);
    }
    
    @SuppressWarnings("unchecked") Fried(Predicate object, int duration){
        this();
        this.duration = duration;
        lstObjects.add(object);
    }
    @SuppressWarnings("unchecked") Fried(Predicate object){
        this();
        this.duration = 5;
        lstObjects.add(object);
    }
    
    public String toString() {
    	return "Fried " + super.toString();
    }
    

}



class Hot extends Predicate
{       
    Hot(){
        lstObjects = new ArrayList<Predicate>(1);
    }
    
    @SuppressWarnings("unchecked") Hot(Predicate object){
        this();
        lstObjects.add(object);
    }
    

}

class Boiled extends Predicate
{       
    public Boiled(){
        lstObjects = new ArrayList<Predicate>(1);
    }
    
    @SuppressWarnings("unchecked") public Boiled(Predicate object, int duration){
        this();
        
        this.duration = duration;
        lstObjects.add(object);
    }
    @SuppressWarnings("unchecked") public Boiled(Predicate object){
        this();
        
        this.duration = 5;
        lstObjects.add(object);
    }

    public String toString() {
    	return "Boiled " + super.toString();
    }
}

class Peeled extends Predicate
{       
    public Peeled(){
        lstObjects = new ArrayList<Predicate>(1);
    }
    
    @SuppressWarnings("unchecked") public Peeled(Predicate object){
        this();
        
        duration = 1;
        lstObjects.add(object);
    }

    public String toString() {
    	return "Peeled " + super.toString();
    }
}

class Beaten extends Predicate
{       
    public Beaten(){
        lstObjects = new ArrayList<Predicate>(1);
    }
    
    @SuppressWarnings("unchecked") public Beaten(Predicate object){
        this();
        lstObjects.add(object);
    }

    public String toString() {
    	return "Beaten " + super.toString();
    }
}